package edu.uob;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CmdParser {
    public static String globalDbName; // 全局 dbName 变量
    private int index;
    private String input;

    public Cmd parse(String cmdString) {
        input = cmdString;
        index = 0;
        return parseCmd();
    }

    private Cmd parseCmd() {
        CmdType cmdType = parseCmdType();
        if (cmdType != null && match(";")) {
            return new Cmd(cmdType);
        } else {
            throw new IllegalArgumentException("[ERROR]: Invalid command syntax");
        }
    }

    private CmdType parseCmdType() {
        skipWhitespace();
        if (match("USE")) {
            skipWhitespace();
            String dbName = parseDbName();
            globalDbName = dbName;
            return new CmdType(CmdTypeEnum.USE, dbName);
        } else if (match("CREATE")) {
            skipWhitespace();
            if (match("DATABASE")) {
                skipWhitespace();
                String dbName = parseDbName();
                return new CmdType(CmdTypeEnum.CREATE_DB, dbName);
            } else if (match("TABLE")) {
                skipWhitespace();
                String tblName = parseTblName();
                if (match("(")) {
                    List<String> attrList = parseAttrList();
                    if (match(")")) {
                        String dbname = globalDbName;
                        return new CmdType(CmdTypeEnum.CREATE_ATTR, dbname, tblName, attrList);
                    }
                } else {
                    String dbname = globalDbName;
                    return new CmdType(CmdTypeEnum.CREATE_TBL, dbname, tblName);
                }
            }
        } else if (match("DROP")) {
            skipWhitespace();
            if (match("DATABASE")) {
                skipWhitespace();
                String dbName = parseDbName();
                return new CmdType(CmdTypeEnum.DROP_DB, dbName);
            } else if (match("TABLE")) {
                skipWhitespace();
                String tblName = parseTblName();
                String dbname = globalDbName;
                return new CmdType(CmdTypeEnum.DROP_TBL, dbname, tblName);
            }
        } else if (match("ALTER")) {
            skipWhitespace();
            if (match("TABLE")) {
                skipWhitespace();
                String tblName = parseTblName();
                skipWhitespace();
                if (match("ADD")) {
                    skipWhitespace();
                    String attributeName = parseAttrName();
                    String dbname = globalDbName;
                    return new CmdType(CmdTypeEnum.ALTER_ADD, dbname, tblName, attributeName);
                } else if (match("DROP"))
                    skipWhitespace();
                String attributeName = parseAttrName();
                String dbname = globalDbName;
                return new CmdType(CmdTypeEnum.ALTER_DROP, dbname, tblName, attributeName);
            }
        } else if (match("INSERT")) {
            skipWhitespace();
            if (match("INTO")) {
                skipWhitespace();
                String tblName = parseTblName();
                skipWhitespace();
                if (match("VALUES")) {
                    skipWhitespace();
                    if (match("(")) {
                        int VALUESIndex = input.indexOf("VALUES");
                        String afterVALUES = input.substring(VALUESIndex + "VALUES".length()).trim();
                        // 计算子字符串的长度
                        int lengthAfterVALUES = afterVALUES.length();
                        String[] sql = input.split("\\s+");
                        System.out.println("SQL after split: " + Arrays.toString(sql));

                        String ValueList = String.join(" ", Arrays.copyOfRange(sql, 4, sql.length));
                        System.out.println("ValueList: " + ValueList);

                        List<String> Values = parseValue(ValueList);
                        System.out.println("Parsed values: " + Values);

                        index = index + lengthAfterVALUES - 3;
                        System.out.println("Index after processing values: " + index);
                        skipWhitespace();

                        if (match(")")) {
                            skipWhitespace();

                            String dbname = globalDbName;
                            return new CmdType(CmdTypeEnum.INSERT, dbname, tblName, Values);
                        } else {
                            System.err.println("[ERROR]: Expected closing parenthesis ')' not found.");
                        }
                    }
                }
            }
        } else if (match("SELECT")) {
            skipWhitespace();
            List<String> WildAttribList = parseWildAttribList();

            if (match("FROM")) {
                skipWhitespace();
                String tblName = parseTblName();
                skipWhitespace();
                if (match("WHERE")) {

                    int whereIndex = input.indexOf("WHERE");
                    String afterWhere = input.substring(whereIndex + "WHERE".length()).trim();
                    // 计算子字符串的长度
                    int lengthAfterWhere = afterWhere.length();
                    String[] sql = input.split("\\s+");

                    String condition = String.join(" ", Arrays.copyOfRange(sql, 5, sql.length));

                    String allCondition = isValidCondition(condition);
                    if (allCondition.contains("[ERROR]")) {
                        return null;
                    }
                    index = index + lengthAfterWhere - 1;


                    String dbname = globalDbName;
                    String query = input;

                    return new CmdType(CmdTypeEnum.SELECT_WH, dbname, tblName, WildAttribList, condition, query);
                } else {
                    String dbname = globalDbName;
                    String query = input;
                    return new CmdType(CmdTypeEnum.SELECT, dbname, tblName, WildAttribList, query);
                }
            }

        } else if (match("UPDATE")) {
            skipWhitespace();
            String tblName = parseTblName();
            skipWhitespace();
            if (match("SET")) {
                skipWhitespace();
                List<String> NameValueList = parseNameValueList();
                for (String nameValue : NameValueList) {
                    System.out.println("[DEBUG]: Parsed Name-Value Pair: " + nameValue);
                }
                skipWhitespace();
                if (match("WHERE")) {
                    System.out.println("[DEBUG]: Found 'WHERE' keyword.");
                    int whereIndex = input.indexOf("WHERE");
                    String afterWhere = input.substring(whereIndex + "WHERE".length()).trim();
                    // 计算子字符串的长度
                    int lengthAfterWhere = afterWhere.length();
                    String[] sql = input.split("\\s+");
                    String condition = String.join(" ", Arrays.copyOfRange(sql, 7, sql.length));
                    System.out.println("[DEBUG]: Condition: " + condition);
                    String allCondition = isValidCondition(condition);
                    if (allCondition.contains("[ERROR]")) {
                        return null;
                    }
                    index = index + lengthAfterWhere - 1;
                    String dbname = globalDbName;
                    String query = input;
                    return new CmdType(CmdTypeEnum.UPDATE, dbname, tblName, NameValueList, condition, query);
                }
            }
        } else if (match("DELETE")) {
            skipWhitespace();
            if (match("FROM")) {
                skipWhitespace();
                String tblName = parseTblName();
                skipWhitespace();
                if (match("WHERE")) {
                    System.out.println("[DEBUG]: Found 'WHERE' keyword.");
                    int whereIndex = input.indexOf("WHERE");
                    String afterWhere = input.substring(whereIndex + "WHERE".length()).trim();
                    // 计算子字符串的长度
                    int lengthAfterWhere = afterWhere.length();
                    String[] sql = input.split("\\s+");
                    String condition = String.join(" ", Arrays.copyOfRange(sql, 4, sql.length));
                    String allCondition = isValidCondition(condition);
                    if (allCondition.contains("[ERROR]")) {
                        return null;
                    }
                    index = index + lengthAfterWhere - 1;
                    String dbname = globalDbName;
                    String query = input;
                    return new CmdType(CmdTypeEnum.DELETE, dbname, tblName, condition, query);
                }
            }
        }
        return null;
    }

    private List<String> parseNameValueList() {
        List<String> NameValue = new ArrayList<>();
        NameValue.add(parseNameValuePair());
        while (match(",")) {
            skipWhitespace();
            NameValue.add(parseNameValuePair());
        }
        return NameValue;
    }

    private String parseNameValuePair() {
        // 解析属性名称
        String attributeName = parseAttrName();
        System.out.println("[DEBUG]: Parsed attribute name: " + attributeName);

        // 检查 "=" 符号
        if (!match("=")) {
            // 如果没有 "=" 符号，格式错误，输出错误消息
            System.err.println("[ERROR]: Missing '=' symbol.");
            return null;
        }
        System.out.println("[DEBUG]: Found '=' symbol.");

        // 解析值
        String value = parseValueUPDATE();
        if (value == null) {
            // 值解析失败，输出错误消息
            System.err.println("[ERROR]: Value parsing error.");
            return null;
        }
        System.out.println("[DEBUG]: Parsed value: " + value);

        // 返回解析出的名值对
        return attributeName + "=" + value;
    }

    private String parseValueUPDATE() {
        // 查看下一个字符，以确定值的类型
        char nextChar = peekNextChar();
        System.out.println("[DEBUG]: Next character: '" + nextChar + "'");

        // 如果值以单引号开始，则解析字符串字面量
        if (nextChar == '\'') {
            return parseStringLiteral();
        }
        // 如果值是TRUE或FALSE，则解析布尔字面量
        else if (Character.isLetter(nextChar)) {
            return parseBooleanLiteral();
        }
        // 如果值是数字，可以是整数或浮点数
        else if (Character.isDigit(nextChar) || nextChar == '-' || nextChar == '+') {
            return parseNumberLiteral();
        }
        // 如果是NULL字面量，则直接返回
        else if (match("NULL")) {
            return "NULL";
        }
        // 如果以上情况都不符合，则表示值的格式错误
        else {
            System.err.println("[ERROR]: Invalid value format.");
            return null;
        }
    }

    // 解析字符串字面量
    private String parseStringLiteral() {
        consume(); // 消耗开始的单引号
        StringBuilder stringBuilder = new StringBuilder();

        // 解析字符串内容
        while (!match("'")) {
            char nextChar = getNextChar();
            // 如果遇到转义字符，则将其转换为相应的字符
            if (nextChar == '\\') {
                char escapedChar = getNextChar();
                switch (escapedChar) {
                    case 'n':
                        stringBuilder.append('\n');
                        break;
                    case 't':
                        stringBuilder.append('\t');
                        break;
                    case '\\':
                    case '\'':
                        stringBuilder.append(escapedChar);
                        break;
                    default:
                        // 不支持的转义字符，报错
                        System.err.println("[ERROR]: Unsupported escape character '" + escapedChar + "'.");
                        return null;
                }
            } else {
                stringBuilder.append(nextChar);
            }
        }

        return stringBuilder.toString();
    }

    // 解析布尔字面量
    private String parseBooleanLiteral() {
        StringBuilder stringBuilder = new StringBuilder();
        while (Character.isLetter(peekNextChar())) {
            stringBuilder.append(getNextChar());
        }
        String value = stringBuilder.toString().toUpperCase();
        if (value.equals("TRUE") || value.equals("FALSE")) {
            return value;
        } else {
            // 如果不是有效的布尔字面量，则报错
            System.err.println("[ERROR]: Invalid boolean literal: " + value);
            return null;
        }
    }

    // 解析数字字面量
    private String parseNumberLiteral() {
        StringBuilder stringBuilder = new StringBuilder();
        // 判断是否是负数
        if (peekNextChar() == '-') {
            stringBuilder.append(getNextChar());
        } else if (peekNextChar() == '+') {
            getNextChar();
        }

        // 解析数字部分
        while (Character.isDigit(peekNextChar())) {
            stringBuilder.append(getNextChar());
        }

        // 判断是否有小数部分
        if (peekNextChar() == '.') {
            stringBuilder.append(getNextChar());

            // 解析小数部分
            while (Character.isDigit(peekNextChar())) {
                stringBuilder.append(getNextChar());
            }
        }

        return stringBuilder.toString();
    }

    private char peekNextChar() {
        if (index < input.length()) {
            return input.charAt(index);
        } else {
            return '\0'; // 表示已经到达输入的末尾
        }
    }

    // 返回下一个字符，并消耗输入
    private char getNextChar() {
        char nextChar = peekNextChar();
        index++;
        return nextChar;
    }

    private void consume() {
        char nextChar = getNextChar();
        if (nextChar != '\'') {
            // 如果下一个字符不是预期的字符，报错
            System.err.println("[ERROR]: Expected '" + '\'' + "' but found '" + nextChar + "'.");
        }
    }

    private static String isValidCondition(String condition) {
        //检查括号
        if (hasBrackets(condition)) {
            if (!checkBracketCount(condition)) {
                return "[ERROR]: " + condition + " Mismatched bracket count！";
            }
        }

        //检查AND OR
        if (condition.contains("AND") || condition.contains("OR")) {

            String[] conditions = condition.split("(?=(AND|OR))|(?<=(AND|OR))");
            // 初始化存储条件的数组
            String[] conditionArray = new String[conditions.length];

            int conditionIndex = 0;

            for (String str : conditions) {
                if (!str.equals("AND") && !str.equals("OR")) {
                    conditionArray[conditionIndex++] = str;
                }
            }

            for (String s : conditionArray) {
                return parseCondition(s);
            }

        } else {
            return parseCondition(condition);
        }
        return condition;
    }

    public static boolean hasBrackets(String condition) {
        return condition.contains("(") || condition.contains(")");
    }

    public static boolean checkBracketCount(String condition) {
        Stack<Character> stack = new Stack<>();
        for (char ch : condition.toCharArray()) {
            if (ch == '(') {
                stack.push(ch);
            } else if (ch == ')') {
                if (stack.isEmpty()) {
                    return false; // 如果没有左括号匹配，返回false
                }
                stack.pop(); // 左括号匹配，出栈
            }
        }
        return stack.isEmpty(); // 检查栈是否为空，为空说明括号数量匹配
    }

    private static final String CONDITION_PATTERN = "\\s*(\\()?(\\w+)(==|>|<|>=|<=|!=| LIKE )(\\w+|'[^']*'|TRUE|FALSE|\\d*\\.?\\d+|NULL)(\\))?\\s*";

    public static String parseCondition(String condition) {

        condition = condition.replaceAll("\\s*==\\s*", "==")
                .replaceAll("\\s*>\\s*", ">")
                .replaceAll("\\s*<\\s*", "<")
                .replaceAll("\\s*>=\\s*", ">=")
                .replaceAll("\\s*<=\\s*", "<=")
                .replaceAll("\\s*!=\\s*", "!=")
                .replaceAll("\\s*LIKE\\s*", "LIKE"); // Remove spaces around comparison operators

        Pattern pattern = Pattern.compile(CONDITION_PATTERN);
        Matcher matcher = pattern.matcher(condition);

        boolean found = false; // 标志是否找到匹配的条件

        // 使用 while 循环来查找匹配的子字符串
        while (matcher.find()) {
            found = true; // 找到匹配的条件
            String attributeName = matcher.group(2); // 属性名
            String operator = matcher.group(3); // 操作符
            String value = matcher.group(4); // 值

            System.out.println("Attribute Name: " + attributeName);
            System.out.println("Operator: " + operator);
            System.out.println("Value: " + value);


        }

        if (!found) {
            return "[ERROR]: Syntax Error: Invalid condition format." + condition;
        }
        return "[OK]";
    }

    private List<String> parseWildAttribList() {
        if (match("*")) {
            List<String> wildcardList = new ArrayList<>();
            wildcardList.add("*");
            return wildcardList;
        } else {
            return parseAttrList();
        }
    }

    private String[] preprocessValues(String values) {
        // 去除字符串两端的括号和分号
        values = values.trim().replaceAll("^\\(|\\);?$", "");
        // 去除字符串两端的空格
        values = values.trim();
        // 拆分值，以逗号和分号为分隔符
        String[] splitValues = values.split("[,;]");
        System.out.println("Split values: " + Arrays.toString(splitValues));

        // 去除每个值两端的空格，并返回处理后的数组
        for (int i = 0; i < splitValues.length; i++) {
            splitValues[i] = splitValues[i].trim();
        }
        return splitValues;
    }

    private static final String VALUE_PATTERN = "'([^']*)'|TRUE|FALSE|\\+?-?\\d+(?:\\.\\d+)?|NULL";
    private static final Pattern VALUE_REGEX = Pattern.compile(VALUE_PATTERN);

    private List<String> parseValue(String value) {
        String[] splitValues = preprocessValues(value);
        List<String> resultList = new ArrayList<>();

        for (String val : splitValues) {
            Matcher matcher = VALUE_REGEX.matcher(val);
            if (matcher.matches()) {
                // 如果匹配到了，则添加匹配到的值到结果列表
                resultList.add(matcher.group());
                System.out.println("matcher.group()" + matcher.group());
            } else {
                // 如果未匹配到，则输出错误信息
                System.err.println("[ERROR]: Invalid SQL value: " + val);
                // 将 "INVALID_VALUE" 添加到结果列表，以便调试
                resultList.add("INVALID_VALUE");
            }
        }
        return resultList;
    }


    private String parseDbName() {
        return parsePlainText();
    }

    private String parseTblName() {
        return parsePlainText();
    }

    private List<String> parseAttrList() {
        List<String> attrs = new ArrayList<>();
        attrs.add(parseAttrName());
        while (match(",")) {
            skipWhitespace();
            attrs.add(parseAttrName());
        }
        return attrs;
    }

    private String parseAttrName() {
        return parsePlainText();
    }

    private String parsePlainText() {
        StringBuilder builder = new StringBuilder();
        while (index < input.length() && isPlainTextChar(input.charAt(index))) {
            builder.append(input.charAt(index));
            index++;
        }
        skipWhitespace();
        return builder.toString();
    }

    private boolean isPlainTextChar(char c) {
        return Character.isLetterOrDigit(c);
    }

    private void skipWhitespace() {
        while (index < input.length() && Character.isWhitespace(input.charAt(index))) {
            index++;
        }
    }

    private boolean match(String expected) {
        if (input.regionMatches(index, expected, 0, expected.length())) {
            index += expected.length();
            skipWhitespace();
            return true;
        }
        return false;
    }
}
